home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
program
/
cpp112.zoo
/
src
/
process.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-01
|
6KB
|
219 lines
/*---------------------------------------------------------------------*\
| |
| CPP -- a stand-alone C preprocessor |
| Copyright (c) 1993 Hacker Ltd. Author: Scott Bigham |
| |
| Permission is granted to anyone to use this software for any purpose |
| on any computer system, and to redistribute it freely, with the |
| following restrictions: |
| - No charge may be made other than reasonable charges for repro- |
| duction. |
| - Modified versions must be clearly marked as such. |
| - The author is not responsible for any harmful consequences of |
| using this software, even if they result from defects therein. |
| |
| process.c -- general input processing and output |
\*---------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "global.h"
struct file_state {
char *old_curfile;
char *old_curdir;
FILE *old_inf;
unsigned long old_lastline, old_thisline, old_nextline;
};
#define MAX_BLANK_LINES 5
/*
sync_line() -- generate a synchronization line of the form "# line-num
filename", where line-num is determined by |this_line|. Sets |last_line|
to |this_line|. |n| is an additional parameter to print on the line, 1
when you enter a file and 2 when you leave it; normally it is 0 and not
printed
*/
void sync_line(n)
int n;
{
switch (sl_style) {
case SL_NONE:
break;
case SL_LINE:
fprintf(outf, "#line %lu \"%s\"\n", this_line, cur_file);
break;
case SL_NORMAL:
switch (n) {
case 0:
fprintf(outf, "# %lu \"%s\"\n", this_line, cur_file);
break;
case 1:
case 2:
fprintf(outf, "# %lu \"%s\" %d\n", this_line, cur_file, n);
break;
default:
bugchk("can't sync_line(%lu,%d)\n", this_line, n);
exit(1);
}
break;
}
last_line = this_line;
}
/*
synchronize() -- synchronize the line number in the output file with the
input file, either by spitting line feeds or generating a synch line. This
should not be used if the filename has changed; use sync_line() for that.
*/
void synchronize()
{
if (last_line > this_line || this_line - last_line > MAX_BLANK_LINES)
sync_line(0);
else
for (; last_line < this_line; last_line++)
fputc('\n', outf);
}
/*
process_line() -- read a line from the input file token by token, doing
the appropriate thing
*/
static int process_line()
{
register TokenP T;
register Macro *M;
register int start_of_line = 1;
for (;;) {
/*
We must be careful here -- the '#' for a directive cannot come from a
macro expansion.
*/
T = (start_of_line ? token(): exp_token());
if (T->type == EOF_) {
free_token(T);
return 0;
}
if (T->type == EOL) {
if (keep_comments) {
print_token(T);
last_line++;
} else if (!start_of_line) {
fputc('\n', outf);
last_line++;
}
free_token(T);
if (start_of_line)
continue;
else
break;
}
if (start_of_line) {
/* check for preprocessor directive */
if (T->type == POUND) {
free_token(T);
directive();
continue;
}
/*
If we're in the false branch of an #ifdef and we're not a
preprocessor directive, just pitch the line and get the next one.
*/
if (!cond_true()) {
free_token(T);
flush_line();
continue;
}
/*
If we get here, we're dealing with a normal line. We push back the
token we just read and re-read it with exp_token() to make sure it
gets expanded.
*/
if (start_of_line && !in_config_file)
synchronize();
start_of_line = 0;
push_tlist(T);
T = exp_token();
}
print_token(T);
free_token(T);
}
return 1;
}
/* path_of_file() -- extract the pathlist from filename |fnam| */
static char *path_of_file(fnam)
char *fnam;
{
char *s, *path;
if (!(s = strrchr(fnam, PATH_SEP))) {
path = mallok(2);
path[0] = '.';
path[1] = '\0';
} else
path = copy_filename(fnam, (int)(s - fnam));
return path;
}
/*
save_state() -- save various values particular to the current input file,
just before opening a new file to process
*/
static void save_state(FS)
register struct file_state *FS;
{
FS->old_curfile = cur_file;
FS->old_curdir = I_list[0];
FS->old_lastline = last_line;
FS->old_thisline = this_line;
FS->old_nextline = next_line;
FS->old_inf = inf;
}
/* restore_state() -- restore values saved with save_state() */
static void restore_state(FS)
register struct file_state *FS;
{
cur_file = FS->old_curfile;
I_list[0] = FS->old_curdir;
last_line = FS->old_lastline;
this_line = FS->old_thisline;
next_line = FS->old_nextline;
inf = FS->old_inf;
}
/* process_file() -- open and process file |fnam| */
void process_file(fnam)
char *fnam;
{
struct file_state FS;
/* save state values from the previous file */
save_state(&FS);
if (streq(fnam, STDIN_NAME))
inf = stdin;
else if (!(inf = xfopen(fnam, "r")))
fatal("cannot open input file %s", fnam);
cur_file = strdup(fnam);
I_list[0] = path_of_file(fnam);
this_line = next_line = 1;
if (!in_config_file)
sync_line(1);
while (process_line()) ;
if (include_level == 0)
endif_check();
if (inf != stdin)
fclose(inf);
free(cur_file);
free(I_list[0]);
restore_state(&FS);
}